package org.linlinjava.litemall.wx.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.systemConfig.SystemConfig;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallCategory;
import org.linlinjava.litemall.db.domain.LitemallGoods;
import org.linlinjava.litemall.db.service.LitemallAdService;
import org.linlinjava.litemall.db.service.LitemallCategoryService;
import org.linlinjava.litemall.db.service.LitemallGoodsService;
import org.linlinjava.litemall.db.service.LitemallTopicService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

/**
 * @author All
 * @date 10.1
 */
@RestController
@RequestMapping("/wx/home")
public class WxHomeController {
	private final Log logger = LogFactory.getLog(WxHomeController.class);

	private LitemallAdService adService;

	private LitemallGoodsService goodsService;

	private LitemallTopicService topicService;

	private LitemallCategoryService categoryService;

	private static final String KEY = "weChatHomepage";

	@Resource
	private RedisTemplate<String, Object> redisTemplate;

	public WxHomeController(
		LitemallAdService adService, LitemallGoodsService goodsService, LitemallTopicService topicService, LitemallCategoryService categoryService) {
		this.adService = adService;
		this.goodsService = goodsService;
		this.topicService = topicService;
		this.categoryService = categoryService;
	}

	/**
	 * app首页
	 *
	 * @return app首页相关信息
	 * 成功则
	 * {
	 * errno: 0,
	 * errmsg: '成功',
	 * data:
	 * {
	 * banner: xxx,
	 * channel: xxx,
	 * newGoodsList: xxx,
	 * hotGoodsList: xxx,
	 * topicList: xxx,
	 * floorGoodsList: xxx
	 * }
	 * }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("/index")
	public Object index() {
		Map<Object, Object> objectMap = redisTemplate.opsForHash().entries(KEY);
		if (objectMap.size() > 0) {
			return ResponseUtil.ok(objectMap);
		} else {
			getHomePage();
			return ResponseUtil.ok(redisTemplate.opsForHash().entries(KEY));
		}
	}

	@Async
	@Scheduled(cron = "0 0/10 * * * ? ")
	public void getHomePage() {
		logger.info("首页定时任务在执行");
		ExecutorService executorService = Executors.newFixedThreadPool(10);
		//总商品数量
		FutureTask<Integer> goodsCountTask = new FutureTask<>(() -> goodsService.queryOnSale());
		//滚动栏
		FutureTask<List> bannerListTask = new FutureTask<>(() -> adService.queryIndex());
		//种类
		FutureTask<List> channelListTask = new FutureTask<>(() -> categoryService.queryChannel(SystemConfig.getCateGory()));
		//新品首发
		FutureTask<List> newGoodsListTask = new FutureTask<>(() -> goodsService.queryByNew(0, SystemConfig.getNewLimit(), SystemConfig.getCateGoryL2()));
		//top10，按积分>200,最近的一个月
		FutureTask<List> topTenListTask = new FutureTask<>(() -> goodsService.queryByTopTen(SystemConfig.getCateGoryL2()));
		//热门
		FutureTask<List> hotGoodsTask = new FutureTask<>(() -> goodsService.queryByHot(0, SystemConfig.getHotLimit(), SystemConfig.getCateGoryL2()));
		//温馨提示
		FutureTask<List> topicListTask = new FutureTask<>(() -> topicService.queryList(0, SystemConfig.getTopicLimit()));
		//会员商品的二级种类id
		FutureTask<List> memberGoodsNumTask = new FutureTask<>(() -> {
			List<LitemallCategory> categoryList1 = categoryService.getL2ByMemberNum(SystemConfig.getMemberNumber());
			return categoryList1.stream().map(LitemallCategory::getId).collect(Collectors.toList());
		});
		//积分兑换的二级种类id
		FutureTask<List> integralGoodsNumTask = new FutureTask<>(() -> {
			List<LitemallCategory> categoryList1 = categoryService.getL2ByMemberNum(SystemConfig.getCateIntegral());
			return categoryList1.stream().map(LitemallCategory::getId).collect(Collectors.toList());
		});
		// 获取积分和爱币兑换列表
		FutureTask<List> categoryListTask = new FutureTask<>(this::getCategoryList);

		executorService.submit(goodsCountTask);
		executorService.submit(bannerListTask);
		executorService.submit(channelListTask);
		executorService.submit(newGoodsListTask);
		executorService.submit(topTenListTask);
		executorService.submit(hotGoodsTask);
		executorService.submit(topicListTask);
		executorService.submit(memberGoodsNumTask);
		executorService.submit(integralGoodsNumTask);
		executorService.submit(categoryListTask);

		Map<Object, Object> data = new HashMap<>(16);

		try {
			data.put("goodsCount", goodsCountTask.get());
			data.put("word", SystemConfig.getReturnWord());
			data.put("banner", bannerListTask.get());
			data.put("channel", channelListTask.get());
			data.put("newGoodsList", newGoodsListTask.get());
			data.put("top10", topTenListTask.get());
			data.put("hotGoodsList", hotGoodsTask.get());
			data.put("brandList", null);
			data.put("topicList", topicListTask.get());
			data.put("floorGoodsList", categoryListTask.get());
			data.put("memberGoodsNum", memberGoodsNumTask.get());
			data.put("integralGoodsNum", integralGoodsNumTask.get());
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		catch (ExecutionException e) {
			e.printStackTrace();
		}
		finally {
			executorService.shutdown();
		}
		redisTemplate.opsForHash().putAll(KEY, data);
	}

	private List<Map> getCategoryList() {
		List<Map> categoryList = new ArrayList<>();
		List<Integer> list = new ArrayList<Integer>() {{
			add(SystemConfig.getCateIntegral());
			add(SystemConfig.getCatePrice());
		}};
		List<LitemallCategory> allCategoryList = categoryService.findAll();
		List<LitemallCategory> catL1List =
			allCategoryList.stream().sorted(Comparator.comparing(LitemallCategory::getId)).filter(s -> "L1".equals(s.getLevel()) && !"推荐".equals(s.getName()) && list.contains(s.getId()))
				.collect(Collectors.toList());
		if (catL1List.size() > SystemConfig.getCatlogListLimit()) {
			catL1List = catL1List.subList(0, SystemConfig.getCatlogListLimit());
		}
		for (LitemallCategory catL1 : catL1List) {
			List<LitemallCategory> catL2List = allCategoryList.stream().filter(m -> m.getPid().equals(catL1.getId())).collect(Collectors.toList());
			List<Integer> l2List = new ArrayList<>();
			for (LitemallCategory catL2 : catL2List) {
				l2List.add(catL2.getId());
			}
			List<LitemallGoods> categoryGoods;
			if (l2List.size() == 0) {
				categoryGoods = new ArrayList<>();
			} else {
				categoryGoods = goodsService.queryByCategory(l2List, 0, SystemConfig.getCatlogMoreLimit());
			}
			Map<String, Object> catGoods = new HashMap<>(16);
			catGoods.put("id", catL1.getId());
			catGoods.put("name", catL1.getName());
			catGoods.put("goodsList", categoryGoods);
			categoryList.add(catGoods);
		}
		return categoryList;
	}
}